package com.hyd.springIOC.ioc;

import com.hyd.springIOC.controller.HydController;
import com.hyd.springIOC.stereotype.Autowired;
import com.hyd.springIOC.stereotype.Component;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;

public class HydIOC {
//        包名加类名（没有.java后缀）
        private List<String> bean_names;
//        全类路径
        private List<String> file_paths;
//        main方法路径
        private String base_path;
//        包名
        private String base_package;
//        放类实例
        private Map<String,Object> beans = new HashMap<>();


        public HydIOC(String basepath, String basepackage) {

//                处理basepath和basepackage
//                basepath:/D:/javacode/myIOC/out/production/myIOC/com/hyd/springIOC/
//                处理成：D:\javacode\myIOC\out\production\myIOC\com\hyd\springIOC\
                basepath=basepath.substring(1).replace("/","\\");
                this.base_path=basepath;
//                形如：com.hyd.springIOC
                this.base_package=basepackage;
                try{
//                        扫描文件
                        scan_files();
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                }
//                获取实例的名称集合
                this.bean_names = new ArrayList<>();
                init_bean_names();

        }

        private void init_bean_names() {
                for (String file_path : this.file_paths) {
                        file_path = file_path.replace(this.base_path,"");
                        if (file_path.endsWith(".class")){
                                file_path = file_path.substring(0,file_path.length()-6);
                        }
                        String bean_name = this.base_package + "." + file_path.replaceAll(Matcher.quoteReplacement(File.separator),".");
                        this.bean_names.add(bean_name);
                }
        }

        /**
         * 扫描当前路径下的文件
         */
        private void scan_files() throws FileNotFoundException {
                File file = new File(this.base_path);
                this.file_paths = new ArrayList<>();
                if (file.exists()){
                        LinkedList<File> file_lists = new LinkedList<>();
                        file_lists.add(file);
                        while (!file_lists.isEmpty()){
                                File temp_file = file_lists.removeFirst();
                                if (temp_file!=null){
                                        if (temp_file.isDirectory()){
                                                File[] files = temp_file.listFiles();
                                                for (File file1 : files) {
                                                        file_lists.add(file1);
                                                }
                                        }else {
                                                this.file_paths.add(temp_file.getPath());
                                        }
                                }else {
                                        continue;
                                }
                        }
                }else {
                        throw new FileNotFoundException("找不到"+this.base_path+"路径下的文件");
                }
        }

        public void initBeans() {
                for (String bean_name : this.bean_names) {
                        try{
                                Class<?> cl = Class.forName(bean_name);
                                Annotation[] annotations = cl.getDeclaredAnnotations();
                                for (Annotation annotation : annotations) {
                                        if (annotation instanceof Component){
                                                Object o = cl.newInstance();
                                                this.beans.put(cl.getName(),o);
                                        }
                                }
                        } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                        } catch (InstantiationException e) {
                                e.printStackTrace();
                        } catch (IllegalAccessException e) {
                                e.printStackTrace();
                        }
                }

                for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
                        Field[] fields = entry.getValue().getClass().getDeclaredFields();
                        for (Field field : fields) {
                                Annotation[] annotations = field.getDeclaredAnnotations();
                                for (Annotation annotation : annotations) {
                                        if (annotation instanceof Autowired){
                                                String name = field.getType().getName();
                                                Object o = this.beans.get(name);
//                                                设置字段为可访问状态
                                                field.setAccessible(true);
                                                try {
//                                                        将获取的对象实例 o 注入到当前字段所属的对象实例中
                                                        field.set(entry.getValue(),o);
                                                } catch (IllegalAccessException e) {
                                                        e.printStackTrace();
                                                }
                                        }
                                }
                        }
                }
        }

        public Object getInstance(String name) {
                return this.beans.get(name);
        }
}
